//
//  Request.m
//  PatientNew
//
//  Created by xxx on 14-7-11.
//  Copyright (c) 2014年 wtf. All rights reserved.
//

#import "Request.h"
#import "Config.h"
#import "ASIHTTP.h"
#import "Cryptor.h"
#import "NSObject+ToJson.h"
#import "User.h"

#define kSourceId @"sourceId"
#define kDeviceNo @"deviceNo"

#define kCondition @"condition"
#define kUserId @"userId"


@implementation Request

#pragma mark - Creator

+ (Request *)requestWithName:(NSString *)name
{
    return [[Config standardConfig].requests objectForKey:name];
}

+ (Request *)requestWithXmlNode:(DDXMLElement *)node
{
    Request *request = [[Request alloc] init];
    
    request.name = [[node elementForName:kXMLNodeNameRequestName] stringValue];
    request.urlString = [[node elementForName:kXMLNodeNameRequestUrlString] stringValue];
    request.httpMethod = [[node elementForName:kXMLNodeNameRequestHttpMethod] stringValue];
    
    request.signInRequired = [[[node elementForName:kXMLNodeNameRequestSignInRequired] stringValue] boolValue];
    request.secured = [[[node elementForName:kXMLNodeNameRequestSecured] stringValue] boolValue];
    request.cached = [[[node elementForName:kXMLNodeNameRequestCached] stringValue] boolValue];
    
    DDXMLElement *specialTimeOut = [node elementForName:kXMLNodeNameRequestTimeOutSeconds];
    if (specialTimeOut) {
        request.timeOutSeconds = [[specialTimeOut stringValue] floatValue];
    } else {
        request.timeOutSeconds = kTimeOutSecondsDefault;
    }
    
    request.params = [NSMutableDictionary dictionary];
    request.files = [NSMutableDictionary dictionary];
    
    return request;
}

#pragma mark - methods for cookies

- (void)addCookieValue:(NSString *)cookieValue forName:(NSString *)name
{
    NSMutableDictionary *properties = [NSMutableDictionary dictionary];
    [properties setValue:name forKey:NSHTTPCookieName];
    [properties setValue:cookieValue forKey:NSHTTPCookieValue];
    Config *config = [Config standardConfig];
    NSURL *url = [NSURL URLWithString:self.secured ? config.securedBaseUrlString : config.baseUrlString];
    [properties setValue:[url host] forKey:NSHTTPCookieDomain];
    [properties setValue:[NSDate dateWithTimeIntervalSinceNow:60 * 60] forKey:NSHTTPCookieExpires];
    [properties setValue:@"\\" forKey:NSHTTPCookiePath];
    
    NSHTTPCookie *cookie = [[NSHTTPCookie alloc] initWithProperties:properties];
    [self.cookies setObject:cookie forKey:name];
}

- (void)addCookie:(NSHTTPCookie *)cookie forName:(NSString *)name
{
    [self.cookies setObject:cookie forKey:name];
}

- (NSMutableArray *)cookieArray
{
    NSMutableArray *cookieArray = [NSMutableArray array];
    NSArray *keys = [self.cookies allKeys];
    for (id key in keys) {
        [cookieArray addObject:[self.cookies objectForKey:key]];
    }
    return cookieArray;
}

#pragma mark - methods for params

- (void)setValue:(NSString *)value forParam:(NSString *)param
{
    [self.params setObject:value forKey:param];
}

- (void)setFile:(id)file forName:(NSString *)name
{
    [self.files setObject:file forKey:name];
}

#pragma mark - sending request and parsing response

- (NSMutableDictionary *)body
{
    if (!_body)
    {
        _body = [[NSMutableDictionary alloc] init];
        _body[kSourceId] = @"2";
#pragma mark - TODO
        _body[kDeviceNo] = @"iOS12345";
        
        if (_signInRequired)
        {
            if ([User currentUser])
                _body[@"userId"] = [User currentUser].userId;
        }
        _body[@"hasSeniorCourse"] = @"true";
    }
    return _body;
}

- (Response *)response
{
    Config *config = [Config standardConfig];
    
    NSString *requestUrlString = @"";
    
    if ([self.httpMethod isEqualToString:kHttpRequestMethodGet]) {
        requestUrlString = [self.urlString stringByAppendingFormat:@"?%@", [self paramString]];
    } else {
        requestUrlString = self.urlString;
    }
    
    if (self.secured) {
        requestUrlString = [config.securedBaseUrlString stringByAppendingString:requestUrlString];
    } else {
        requestUrlString = [config.baseUrlString stringByAppendingString:requestUrlString];
    }
    
    NSLog(@"request url: %@", requestUrlString);
    
    NSURL *url = [NSURL URLWithString:requestUrlString];
    
    ASIFormDataRequest *asiRequest = [ASIFormDataRequest requestWithURL:url];
    
    // cookies
    NSMutableArray *cookieArray = [self cookieArray];
    if (cookieArray.count > 0) {
        [asiRequest setUseCookiePersistence:NO];
        [asiRequest setRequestCookies:cookieArray];
    }
    
    // adding post data
    if ([self.httpMethod isEqualToString:kHttpRequestMethodPOST]) {
        NSString *str = [self.body prettyJSONString];
        NSLog(@"raw post body: %@", str);
        
        NSData *data = [Cryptor rsaEncryptString:str];
        [asiRequest appendPostData:data];
        
        NSLog(@"rsa crypt data len: %ld", data.length);
    }
    
    // sending request
    [asiRequest setTimeOutSeconds:self.timeOutSeconds];
    [asiRequest startSynchronous];
    
    if (asiRequest.error) {
        return nil;
    }
    if (asiRequest.responseStatusCode != 200 && asiRequest.responseStatusCode != 301) {
        return nil;
    }
    
    if (self.cached && [self.httpMethod isEqualToString:kHttpRequestMethodGet]) {
#pragma mark - todo local cache
        // cached
    }
    
    return [Response responseWithData:asiRequest.responseData andCookies:asiRequest.responseCookies];
}

// url string for http method get
- (NSString *)paramString
{
    NSMutableString *paramString = [NSMutableString string];
    
    for (id key in self.params) {
        NSString *value = [self.params valueForKey:key];
        if (value.length > 0) {
            [paramString appendFormat:@"%@=%@&", key, [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
        }
    }
    
    return paramString;
}

@end
